<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      let a = {
        b: 2,
        c: [2, 3],
        function() {
          console.log(1);
        },
      };

      //   获取数据类型
      function getType(element) {
        return Object.prototype.toString.call(element).slice(8, -1);
      }

      //   let type = getType(a);
      //   console.log(type);

      function deepClone(target, map = new Map()) {
        // 获取传入数据的类型
        let type = getType(target);
        if (type === "Object" || type === "Array") {
          // 声明一个容器拷贝
          let cloneTarget = map.get(target);

          if (cloneTarget) {
            return cloneTarget;
          }

          // 处理对象
          if (type === "Object") {
            cloneTarget = {};
            map.set(target, cloneTarget);
            Object.keys(target).forEach((item) => {
              cloneTarget[item] = deepClone(target[item], map);
            });
          }
          // 处理数组
          else if (type === "Array") {
            cloneTarget = [];
            map.set(target, cloneTarget);
            target.forEach((item, index) => {
              cloneTarget[index] = deepClone(item, map);
            });
          }
          return cloneTarget;
        } else {
          return target;
        }
      }

      let b = {
        a: 3,
        b: { c: 1 },
        c: [1],
        function() {
          console.log(1);
        },
      };
      //   console.log(deepClone(b));
      //   let c = deepClone(b);
      //   console.log(c);

      const obj = {
        a: {
          m: 3,
        },
        b: [2],
        c: 3,
        fn: function () {},
      };

      obj.a.c = obj.b;
      obj.b[1] = obj.a;

      //   let d = deepClone(obj);
      //   console.log(obj);
    </script>

    <script>
      //   let m = { f: 1 };
      //   console.log(getType(m));

      function MyCloneDeep(target, map = new Map()) {
        let type = getType(target);
        if (type === "Object" || type === "Array") {
          let cloneTarget = map.get(target);
          if (cloneTarget) return cloneTarget;

          if (type === "Object") {
            cloneTarget = {};
            map.set(target, cloneTarget);
            Object.keys(target).forEach((item) => {
              cloneTarget[item] = MyCloneDeep(target[item], map);
            });
          } else if (type === "Array") {
            cloneTarget = [];
            map.set(target, cloneTarget);
            target.forEach((item, index) => {
              cloneTarget[index] = MyCloneDeep(item, map);
            });
          }
          return cloneTarget;
        } else {
          return target;
        }
      }
      console.log(obj);
      console.log(MyCloneDeep(obj));
    </script>
  </body>
</html>
